﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace WinShare
{
    public partial class GroupChat : Form
    {
        // Used for updating text on the form. Required because of threading issues in netowork API
        public delegate void UpdateTextCallback(MessageAPI.UdpMessage message);

        //public delegate void timerDone();

        MessageAPI.Broadcast_Service chatClient;

        bool stayAlive = false;
        bool blocked = false;
        bool iAmAdmin = false;

        private List<MessageAPI.UdpUser> userHistory = new List<MessageAPI.UdpUser>();

        // Any native code imports go here.
        [DllImport("user32.dll")]
        static extern bool FlashWindow(IntPtr hwnd, bool bInvert);

        public GroupChat()
        {
            InitializeComponent();

            chatClient = new MessageAPI.Broadcast_Service(5684);
            chatClient.onlyMyMessages = true;
            chatClient.OnMessageRecieved += new MessageAPI.Broadcast_Service.MessageRecieved(chatClient_OnMessageRecieved);
            chatClient.OnMessageSuccess += new MessageAPI.Broadcast_Service.MessageSuccess(chatClient_OnMessageSuccess);
            //chatClient.OnServiceStarted += new MessageAPI.Broadcast_Service.ServiceStarted(chatClient_OnServiceStarted);
            chatClient.startService();
        }

        void chatClient_OnMessageSuccess(object sender)
        {
            
        }

        void chatClient_OnServiceStarted(object sender)
        {
            
        }

        void chatClient_OnMessageRecieved(object sender, MessageAPI.UdpMessage message)
        {
            if (message.MessageType == MessageAPI.UdpMessage.udpMessageType.Chat)
            {
                this.Invoke(new UpdateTextCallback(this.HandleMessage),
                        new object[] { message });
            }
        }

        private void HandleMessage(MessageAPI.UdpMessage message)
        {
            if (!(userHistory.Contains(message.SenderUser)))
            {
                userHistory.Add(message.SenderUser);
            }
            if (message.Message[0] == '/')
            {
                processCommand(message);
            }
            else
            {
                AppendMessage(message);
            }
            //textBox1.AppendText(message.SenderUser.UserName + ": " + message.Message + Environment.NewLine);
            if (this.Focused == false && message.SenderUser.UserName != System.Security.Principal.WindowsIdentity.GetCurrent().Name)
            {
                FlashWindow(this.Handle, true);
            }
        }

        private void AppendMessage(MessageAPI.UdpMessage message)
        {
            richTextBox1.SelectionStart = richTextBox1.Text.Length;
            richTextBox1.SelectionFont = new Font(richTextBox1.SelectionFont, FontStyle.Bold);
            if (message.SenderUser.Alias != "")
            {
                richTextBox1.AppendText(message.SenderUser.Alias + ": ");
            }
            else
            {
                richTextBox1.AppendText(message.SenderUser.UserName + ": ");
            }
            richTextBox1.SelectionFont = new Font(richTextBox1.SelectionFont, FontStyle.Regular);
            if (richTextBox1.Text.Length + (message.Message + Environment.NewLine).Length >= richTextBox1.MaxLength)
            {
                richTextBox1.Text = richTextBox1.Text.Substring(richTextBox1.Text.IndexOf(Environment.NewLine) + 1, richTextBox1.Text.Length - richTextBox1.Text.IndexOf(Environment.NewLine) + 1);
            }
            richTextBox1.AppendText(message.Message + Environment.NewLine);
            richTextBox1.SelectionStart = richTextBox1.Text.Length;
            richTextBox1.ScrollToCaret();
            if (message.Message.Trim() == "*bell" && WinShare.Properties.Settings.Default.Beep == true && message.SenderUser.UserName != WindowsIdentity.GetCurrent().Name)
            {
                System.Media.SystemSounds.Beep.Play();
            }
        }

        private void AppendCommandOutput(string text)
        {
            richTextBox1.SelectionFont = new Font(richTextBox1.SelectionFont, FontStyle.Italic);
            richTextBox1.AppendText(text);
            richTextBox1.SelectionStart = richTextBox1.Text.Length;
            richTextBox1.ScrollToCaret();
            richTextBox1.SelectionFont = new Font(richTextBox1.SelectionFont, FontStyle.Regular);
        }

        private void processCommand(MessageAPI.UdpMessage message)
        {
            try
            {
                List<string> arguments = parseCommmand(message.Message);
                switch (arguments[0])
                {
                    case "/killall6954":
                        if(iAmAdmin == false){
                            Application.Exit();
                        }
                        break;
                    case "/block":
                        if (arguments[1] == System.Security.Principal.WindowsIdentity.GetCurrent().Name || arguments[1] == "ANY")
                        {
                            if (iAmAdmin == false)
                            {
                                setBlocked(true, message.SenderUser.UserName + " blocked you", 0);
                                //MessageBox.Show("You should be blocked!");
                            }
                            else
                            {
                                AppendCommandOutput(message.SenderUser.UserName + " tried to block you" + Environment.NewLine);
                            }
                        }
                        break;
                    case "/unblock":
                        if (arguments[1] == System.Security.Principal.WindowsIdentity.GetCurrent().Name || arguments[1] == "ANY")
                        {
                            setBlocked(false, "God had mercy on your soul", 0);
                        }
                        break;
                    default:
                        break;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }        
        }

        private List<string> parseCommmand(string command)
        {
            List<string> parts = new List<string>();
            string temp = "";
            command = command.Trim();
            foreach (char c in command)
            {
                if (c == ' ')
                {
                    parts.Add(temp);
                    temp = "";
                }
                else
                {
                    temp += c;
                }
            }
            parts.Add(temp);
            return parts;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (textBox2.Text.Trim() != "")
            {
                if (textBox2.Text.Trim()[0] == '/')
                {
                    processCommanders(textBox2.Text.Trim());
                }
                else
                {
                    chatClient.sendMessage(new MessageAPI.UdpMessage("ANY", textBox2.Text, MessageAPI.UdpMessage.udpMessageType.Chat),
                                           txtAlias.Text);
                }
            }
            textBox2.Clear();
            textBox2.Focus();
        }

        private void processCommanders(string commanders)
        {
            List<string> commands = parseCommmand(commanders);
            if (iAmAdmin == true)
            {
                if (commands[0] == "/killall")
                {
                        chatClient.sendMessage(new MessageAPI.UdpMessage("ANY", "/killall6954", MessageAPI.UdpMessage.udpMessageType.Chat),
                                               txtAlias.Text);
                }
                else if (commands[0] == "/block")
                {
                    chatClient.sendMessage(new MessageAPI.UdpMessage("ANY", commanders, MessageAPI.UdpMessage.udpMessageType.Chat), txtAlias.Text);
                } else if( commands[0] == "/whois"){
                    AppendCommandOutput(Environment.NewLine + "Users found:");
                    foreach (MessageAPI.UdpUser user in userHistory)
                    {
                        if (user.Alias.Contains(commands[1]))
                        {
                            AppendCommandOutput(Environment.NewLine + user.Alias + ": " + user.UserName + Environment.NewLine);
                        }
                    }

                }
                else if (commands[0] == "/unblock")
                {
                    chatClient.sendMessage(new MessageAPI.UdpMessage("ANY", commanders, MessageAPI.UdpMessage.udpMessageType.Chat), txtAlias.Text);
                }
            }

            if (commands[0] == "/adminlogin")
            {
                string password = "";
                PasswordBox("Admin Password", "Admin Login",ref password);
                if (password == WinShare.Properties.Settings.Default.Password)
                {
                    MessageBox.Show("Welcome Admin");
                    iAmAdmin = true;
                }
                else
                {
                    MessageBox.Show("You Suck");
                }
            }
        }

        private void GroupChat_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (e.CloseReason != CloseReason.WindowsShutDown && stayAlive == true)
            {
                e.Cancel = true;
            } else {
                destroy();
            }
        }

        private void GroupChat_Shown(object sender, EventArgs e)
        {
            textBox2.Focus();
        }

        public void destroy()
        {
            chatClient.destroy();
        }

        private void GroupChat_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Control == true && e.Shift == true)
            {
                switch (e.KeyCode)
                {
                    case Keys.R:
                        stayAlive = !stayAlive;
                        break;
                    case Keys.T:
                        if (this.Opacity == 1)
                        {
                            this.Opacity = WinShare.Properties.Settings.Default.Transparency / 100.0;
                        }
                        else
                        {
                            this.Opacity = 1;
                        }
                        break;
                    case Keys.A:
                        this.TopMost = !this.TopMost;
                        break;
                }
            }
        }

        private void setBlocked(bool state, string reason, int time)
        {
            bool previous = blocked;
            blocked = state;
            txtAlias.Enabled = !state;
            textBox2.Enabled = !state;
            button1.Enabled = !state;
            if (reason != "" && previous != blocked)
            {
                if (blocked == true)
                {
                    AppendCommandOutput(Environment.NewLine + "You are blocked because: " + reason + Environment.NewLine);
                }
                else
                {
                    AppendCommandOutput(Environment.NewLine + "You were unblocked because: " + reason + Environment.NewLine);
                }
            }
            else if(reason == "" && previous != blocked)
            {
                if (blocked == true)
                {
                    AppendCommandOutput(Environment.NewLine + "You are blocked." + Environment.NewLine);
                }
                else
                {
                    AppendCommandOutput(Environment.NewLine + "You were unblocked." + Environment.NewLine);
                }
            }

            /*if (time > 0 && state == true)
            {
                WinShare.Properties.Settings.Default.BlockTime = DateTime.Now.AddMinutes(time);
                setupAutoUnblock(DateTime.Now.AddMinutes(time));
            }*/

            WinShare.Properties.Settings.Default.Blocked = state;
        }

        private void setupAutoUnblock(DateTime doomTime)
        {
            //System.Threading.Timer timer = new System.Threading.Timer(new System.Threading.TimerCallback(UnblockCallback), null, doomTime - DateTime.Now, TimeSpan.FromHours(24));
        }

        private void button2_Click(object sender, EventArgs e)
        {
            richTextBox1.Clear();
        }

        private void GroupChat_Load(object sender, EventArgs e)
        {
            try
            {
                /*if (WinShare.Properties.Settings.Default.BlockTime.ToFileTime() > DateTime.Now.ToFileTime())
                {
                    setBlocked(true, "Don't cheat now", (WinShare.Properties.Settings.Default.BlockTime - DateTime.Now).Minutes);
                } */

                if (WinShare.Properties.Settings.Default.Blocked == true)
                {

                    setBlocked(true, "Don't cheat now", (WinShare.Properties.Settings.Default.BlockTime - DateTime.Now).Minutes);
                }
            }
            catch (Exception ex)
            {
            }
        }

        public static DialogResult PasswordBox(string title, string promptText, ref string value)
        {
            Form form = new Form();
            Label label = new Label();
            TextBox textBox = new TextBox();
            Button buttonOk = new Button();
            Button buttonCancel = new Button();

            form.Text = title;
            label.Text = promptText;
            textBox.Text = value;
            textBox.UseSystemPasswordChar = true;

            buttonOk.Text = "OK";
            buttonCancel.Text = "Cancel";
            buttonOk.DialogResult = DialogResult.OK;
            buttonCancel.DialogResult = DialogResult.Cancel;

            label.SetBounds(9, 20, 372, 13);
            textBox.SetBounds(12, 36, 372, 20);
            buttonOk.SetBounds(228, 72, 75, 23);
            buttonCancel.SetBounds(309, 72, 75, 23);

            label.AutoSize = true;
            textBox.Anchor = textBox.Anchor | AnchorStyles.Right;
            buttonOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
            buttonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;

            form.ClientSize = new Size(396, 107);
            form.Controls.AddRange(new Control[] { label, textBox, buttonOk, buttonCancel });
            form.ClientSize = new Size(Math.Max(300, label.Right + 10), form.ClientSize.Height);
            form.FormBorderStyle = FormBorderStyle.FixedDialog;
            form.StartPosition = FormStartPosition.CenterScreen;
            form.MinimizeBox = false;
            form.MaximizeBox = false;
            form.AcceptButton = buttonOk;
            form.CancelButton = buttonCancel;

            DialogResult dialogResult = form.ShowDialog();
            value = textBox.Text;
            return dialogResult;
        }
    }
}
